package yuresp

import (
	"compress/gzip"
	"net/http"

	"google.golang.org/protobuf/encoding/protojson"
	"google.golang.org/protobuf/proto"
	"google.golang.org/protobuf/types/known/anypb"
)

// 返回code值
const (
	CodeOK int = iota
	CodeErr
)

// PbRespOK pb返回正确
func PbRespOK(w http.ResponseWriter, m proto.Message) error {
	w.Header().Set("Content-Type", "application/json;charset=UTF-8")
	w.WriteHeader(http.StatusOK)
	data, _ := anypb.New(m)
	r, err := protojson.MarshalOptions{EmitUnpopulated: true}.Marshal(&PbResp{
		Code:    int32(CodeOK),
		Message: "",
		Data:    data,
	})
	if err != nil {
		return err
	}
	_, err = w.Write(r)
	return err
}

// GzipPbRespOK gzip压缩pb返回正确
func GzipPbRespOK(w http.ResponseWriter, m proto.Message) error {
	w.Header().Set("Content-Type", "application/json;charset=UTF-8")
	w.Header().Set("Content-Encoding", "gzip")
	w.WriteHeader(http.StatusOK)
	gz := gzip.NewWriter(w)
	defer gz.Close()
	data, _ := anypb.New(m)
	r, err := protojson.MarshalOptions{EmitUnpopulated: true}.Marshal(&PbResp{
		Code:    int32(CodeOK),
		Message: "",
		Data:    data,
	})
	if err != nil {
		return err
	}
	_, err = gz.Write(r)
	return err
}

// PbRespOK pb返回错误
func PbRespError(w http.ResponseWriter, err error) error {
	w.Header().Set("Content-Type", "application/json;charset=UTF-8")
	w.WriteHeader(http.StatusOK)
	r, err := protojson.MarshalOptions{EmitUnpopulated: true}.Marshal(&PbResp{
		Code:    int32(CodeErr),
		Message: err.Error(),
	})
	if err != nil {
		return err
	}
	_, err = w.Write(r)
	return err
}

// Resp http统一返回结构
type Resp[T any] struct {
	Code int    `json:"code"`
	Msg  string `json:"msg,omitempty"`
	Data T      `json:"data,omitempty"`
}

// RespOK 创建一个返回OK的结构
func RespOK[T any](data T) *Resp[T] {
	return &Resp[T]{Code: CodeOK, Data: data}
}

// RespErr 创建一个返回error的结构
func RespErr(err error) *Resp[any] {
	return &Resp[any]{Code: CodeErr, Msg: err.Error()}
}

// RespMsg 创建一个返回字符串信息的结构
func RespMsg(code int, msg string) *Resp[any] {
	return &Resp[any]{Code: code, Msg: msg}
}

// NewResp 创建一个返回结构
func NewResp[T any](code int, msg string, data T) *Resp[T] {
	return &Resp[T]{Code: code, Msg: msg, Data: data}
}
